load VS initialize

共同点

方法只会被调用一次(相对于runtime而言)

区别

load方法

声明一个SuperClass类继承与NSObject

1
2
3
4
@implementation SuperClass
+ (void) load {
NSLog(@"加载load方法");
}
1
2
3
4
5
6
int main(int argc, char * argv[]) {
@autoreleasepool {
NSLog(@"main");
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

控制台打印输出 load main

得出结论:load方法在程序启动前就会调用。在main函数之前调用。

initialize方法

执行以下代码

1
2
3
4
5
6
7
+ (void) initialize {
NSLog(@"%@ %s", [self class], __FUNCTION__);
}

+ (void) load {
NSLog(@"%@ %s", [self class], __FUNCTION__);
}

控制台打印输出

1
2
SuperClass +[SuperClass initialize]
SuperClass +[SuperClass load]

为什么initialize方法会再load方法前调用呢?通过Apple的文档

1
The runtime sends initialize to each class in a program exactly one time just before the class, or any class that inherits from it, is sent its first message from within the program. (Thus the method may never be invoked if the class is not used.) The runtime sends the initialize message to classes in a thread-safe manner. Superclasses receive this message before their subclasses.

得知: initialize方法在类的第一个方法被调用前调用。即先执行load方法中的[self class] 就会调用initialize方法。

子类会调用父类的initialize

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@interface ChildClass : SuperClass

@end


@implementation SuperClass

+ (void) initialize {
NSLog(@"%@ %s", [self class], __FUNCTION__);
}

@end


@implementation ChildClass

+ (void)load
{
NSLog(@"%@ %s", [self class], __FUNCTION__);

}

@end

还是导入头文件而不去使用它控制台打印输出

1
2
3
SuperClass +[SuperClass initialize]
ChildClass +[ChildClass initialize]
ChildClass +[ChildClass load]

类别(Category)中的+(void)load的+(void)initialize

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/******* Interface *******/
@interface MainClass : NSObject
@end

/******* Category Implementation *******/
@implementation MainClass(Category)

+ (void) load {
NSLog(@"%@ %s", [self class], __FUNCTION__);
}

+ (void) initialize {
NSLog(@"%@ %s", [self class], __FUNCTION__);
}

@end

@implementation MainClass(OtherCategory)

+ (void) load {
NSLog(@"%@ %s", [self class], __FUNCTION__);
}

+ (void) initialize {
NSLog(@"%@ %s", [self class], __FUNCTION__);
}

@end

/******* Implementation *******/
@implementation MainClass

+ (void) load {
NSLog(@"%@ %s", [self class], __FUNCTION__);
}

+ (void) initialize {
NSLog(@"%@ %s", [self class], __FUNCTION__);
}

@end

import 之后

MainClass +[MainClass(OtherCategory) initialize]
MainClass +[MainClass load]
MainClass +[MainClass(Category) load]
MainClass +[MainClass(OtherCategory) load]

先执行类自身的实现,再执行类别(Category)中的实现

不需要调用[super load] 和 [super initialize]

1
2
3
4
5
6
7
8
9
+ (void)initialize {
//do initialization thing
[super initialize];
}

+ (void) load {
//do some loading things
[super load];
}

这样写是多余的

开发过程中需要注意

在Objective-C中,运行时会自动调用每个类的两个方法。+load会在类初始加载时调用,+initialize会在第一次调用类的类方法或实例方法之前被调用。这两个方法是可选的,且只有在实现了它们时才会被调用。由于method swizzling会影响到类的全局状态,因此要尽量避免在并发处理中出现竞争的情况。+load能保证在类的初始化过程中被加载,并保证这种改变应用级别的行为的一致性。相比之下,+initialize在其执行时不提供这种保证–事实上,如果在应用中没为给这个类发送消息,则它可能永远不会被调用

参考链接:
Objective C类方法load和initialize的区别